<?php
/**
 * @package DBpretty
 * @author WiFeng
 * @link http://521-wf.com
 */

class DBpretty_Do extends Typecho_Widget implements Widget_Interface_Do {
	
	public $options;

	public function execute() {
		$this->widget('Widget_User')->pass('administrator', false);
		$this->options = $this->widget('Widget_Options');
	}
	
	public function action() {
		$this->on($this->request->is('operation=export'))->exportDB();
		$this->on($this->request->is('operation=exec'))->execSQL();
		$this->on($this->request->is('operation=optimize'))->optimizeDB();
		$this->on($this->request->is('operation=delete'))->deleteFile();
		$this->on($this->request->is('operation=download'))->downloadFile();
	}
	
	public function exportDB() {
		$type = $this->request->type;
		$tablenames = $this->request->tablenames;
		$sqlcompat = $this->request->sqlcompat;
		$usezip = $this->request->usezip;
		$backupfilename = $this->request->filename;
		
		$backupdir = $this->getBackupDir();
		
		if(empty($backupfilename)) {
			$this->response->throwJson(array('msg' => _t('请您先认真填写备份文件名'), 'status' => 'error'));
		} elseif(!$backupdir) {
			$this->response->throwJson(array('msg' => _t('备份目录没有设置或者不合理，请先到插件设置项中对其进行设置'), 'status' => 'error'));
		} elseif(strpos($backupdir, 'plugins') === 0 || strpos($backupdir, 'themes') === 0 || strpos($backupdir, 'uploads') === 0) {
			$this->response->throwJson(array('msg' => _t('备份目录不能是 plugins、themes、uploads等这些系统目录'), 'status' => 'error'));
		}
		
		$realBackupDir = $this->getRealBackupDir();
		if(!is_dir($realBackupDir)) {
			if(!mkdir($realBackupDir, 0777, true)) {
				$this->response->throwJson(array('msg' => _t('备份目录创建失败，请检查usr目录的权限是否可写'), 'status' => 'error'));
			}
		} else {
			if(file_exists($realBackupDir.$backupfilename.'.sql')) {
				$this->response->throwJson(array('msg' => _t('备份目录下已经有同名文件，请您换个文件名'), 'status' => 'error'));
			}
		}
		touch($realBackupDir.'index.htm');

		$backupfilename = urlencode($backupfilename);

		$dumpfile = self::getAbsoluteBackupDir() . $backupfilename.'.sql';

		if($type == 'all') {
			$tablenames = array_keys(DBpretty_Options::getAllTables());
		} else {
			$tablenames = explode(',', $tablenames);
		}
		
		$charset = Helper::options()->charset;
		$charset = strtolower(substr($charset, 0, 3)) == 'utf' ? 'utf8' : strtolower($charset);

		$dbName = Helper::options()->plugin('DBpretty')->dbname;
		$dbHost = Helper::options()->plugin('DBpretty')->dbhost;
		$dbUser = Helper::options()->plugin('DBpretty')->dbuser;
		$dbPass = Helper::options()->plugin('DBpretty')->dbpass;
		$dbPort = Helper::options()->plugin('DBpretty')->dbport;
		$dbCharset = Helper::options()->plugin('DBpretty')->dbcharset;
		
		$dbInfo = $this->getDBInfo($dbHost, $dbUser, $dbPass, $dbCharset, $dbPort, $dbName);
		$dbVersion = $dbInfo['version'];
		$mysql_base = $dbInfo['mysql_base'];
		
		$tablesstr = '';
		foreach($tablenames as $table) {
			$tablesstr .= '"'.$table.'" ';
		}
		
		@unlink($dumpfile);
		$extendins = 0;
		$mysqlbin = $mysql_base == '/' ? '' : addslashes($mysql_base).'bin/';
		
		shell_exec($mysqlbin.'mysqldump --force --quick '.($dbVersion > '4.1' ? '--skip-opt --create-options' : '-all').' --add-drop-table'.($extendins == 1 ? ' --extended-insert' : '').''.($dbVersion > '4.1' && $sqlcompat == 'MYSQL40' ? ' --compatible=mysql40' : '').' --host="'.$dbHost.'"'.($dbPort ? (is_numeric($dbPort) ? ' --port="'.$dbPort.'"' : ' --socket="'.$dbPort.'"') : '').' --user="'.$dbUser.'" --password="'.$dbPass.'" "'.$dbName.'" '.$tablesstr.' > '.$dumpfile);
		
		if(@file_exists($dumpfile)) {
			if($usezip) {
				require_once __TYPECHO_ROOT_DIR__ . __TYPECHO_PLUGIN_DIR__ . '/DBpretty/ZipFile.php';
				$zip = new ZipFile();
				$zipfilename = self::getAbsoluteBackupDir() . $backupfilename.'.zip';
				$unlinks = array();
				
				$fp = fopen($dumpfile, 'r');
				$content = @fread($fp, filesize($dumpfile));
				fclose($fp);
				$zip->addFile($content, basename($dumpfile));

				$fp = fopen($zipfilename, 'w');
				if(@fwrite($fp, $zip->file()) !== FALSE) {
						@unlink($dumpfile);
				} 
			}
			$this->widget('Widget_Notice')->set(_t('备份成功啦！'), NULL, 'success');
			$this->response->throwJson(array('msg' => _t('备份成功啦！'), 'status' => 'ok'));
		} else {
			$this->response->throwJson(array('msg' => _t('备份失败啦,请您联系插件开发者'), 'status' => 'error'));
		}
	}
	
	public function optimizeDB() {
		echo __METHOD__;
	}

	public static function getBackupDir() {
		$backupdir = trim(Helper::options()->plugin('DBpretty')->backupdir, '/');
		$backupdir = str_replace(array('../', './', '..\\', '.\\'), '', $backupdir);
		return $backupdir;
	}

	public static function getRealBackupDir() {
		$backupdir = self::getBackupDir();
		if(empty($backupdir)) {
			return false;
		} else {
			return './usr/'.$backupdir.'/';
		}
	}
	
	public static function getAbsoluteBackupDir($addslashes = true) {
		$realBackupDir = self::getRealBackupDir();
		if($addslashes) {
			return addslashes(str_replace('\\', '/', __TYPECHO_ROOT_DIR__ . $realBackupDir . '/'));
		} else {
			return str_replace('\\', '/', __TYPECHO_ROOT_DIR__ . $realBackupDir . '/');
		}
	}

	public function getBackupDirUrl() {
		$realBackupDir = self::getRealBackupDir();
		return $this->options->siteUrl.$realBackupDir;
	}

	public function deleteFile() {
		$filenames = $this->request->filename;
		$absoluteBackupDir = $this->getAbsoluteBackupDir();
		$deleteCount = 0;
		if(is_array($filenames) && !empty($filenames)) {
			foreach($filenames as $name) {
				if(file_exists($absoluteBackupDir.$name)) {
					if(unlink($absoluteBackupDir.$name)) {
						$deleteCount ++ ;
					}
				}
			}
		}

		/** 设置提示信息 */
        $this->widget('Widget_Notice')->set($deleteCount > 0 ? _t('备份文件已经被删除') : _t('没有备份文件被删除'), NULL,
        $deleteCount > 0 ? 'success' : 'notice');

        /** 返回原网页 */
        $this->response->goBack();
	}

	public function execSQL() {
		$filename = $this->request->importfilename;
		$absoluteBackupDir = $this->getAbsoluteBackupDir(true);
		$iszip = false;
		if(file_exists($absoluteBackupDir.$filename)) {

			if('zip' == substr($filename, -3)) {
				$iszip = true;
				require_once __TYPECHO_ROOT_DIR__ . __TYPECHO_PLUGIN_DIR__ . '/DBpretty/ZipFile.php';
				$unzip = new SimpleUnzip();
				$backupdir = self::getAbsoluteBackupDir();
				$unzip->ReadFile($absoluteBackupDir.$filename);

				if($unzip->Count() == 0 || $unzip->GetError(0) != 0 || !preg_match("/\.sql$/i", $importfile = $unzip->GetName(0))) {
					$this->widget('Widget_Notice')->set(_t('导入文件不合理！'), NULL, 'error');
					$this->response->goBack();
				} else {
					$tmpdir = $absoluteBackupDir.'tmp/';
					if(!is_dir($tmpdir)) {
						if(!@mkdir($tmpdir, 0777)) {
							$this->widget('Widget_Notice')->set(_t('临时目录创建失败，请先检查备份目录是否具有可写权限！'), NULL, 'error');
							$this->response->goBack();
						}
						touch($tmpdir.'index.htm');
					}
					
					$sqlFiles = array();
					foreach($unzip->Entries as $entry) {
						if(preg_match("/\.sql$/i", $entry->Name)) {
							$fp = fopen($tmpdir.$entry->Name, 'w');
							fwrite($fp, $entry->Data);
							fclose($fp);
							$sqlFiles[] = $entry->Name;
						}
					}
					$filename = 'tmp/'.$sqlFiles[0];
				}
			}
			
			$dbName = Helper::options()->plugin('DBpretty')->dbname;
			$dbHost = Helper::options()->plugin('DBpretty')->dbhost;
			$dbUser = Helper::options()->plugin('DBpretty')->dbuser;
			$dbPass = Helper::options()->plugin('DBpretty')->dbpass;
			$dbPort = Helper::options()->plugin('DBpretty')->dbport;
			$dbCharset = Helper::options()->plugin('DBpretty')->dbcharset;

			$dbInfo = $this->getDBInfo($dbHost, $dbUser, $dbPass, $dbCharset, $dbPort, $dbName);
			$mysql_base = $dbInfo['mysql_base'];

			$mysqlbin = $mysql_base == '/' ? '' : addslashes($mysql_base).'bin/';
			
			shell_exec($mysqlbin.'mysql --host="'.$dbHost.'"'.($dbPort ? (is_numeric($dbPort) ? ' --port="'.$dbPort.'"' : ' --socket="'.$dbPort.'"') : '').' --user="'.$dbUser.'" --password="'.$dbPass.'" "'.$dbName.'" < '.$absoluteBackupDir.$filename.' --default-character-set='.$dbCharset);
			
			if(isset($tmpdir) && !empty($tmpdir)) {
				if($handle = opendir($tmpdir)) {
					while(false !== ($file = readdir($handle))) {
						if($file != 'index.htm') {
							@unlink($tmpdir.$file);
						}
						
					}
					closedir($handle);
				}
			}
			$this->keepLogin($dbInfo['dbObj']);
			$this->widget('Widget_Notice')->set(_t('导入成功了，请您仔细核实数据'), NULL, 'success');
			$this->response->goBack($this->options->adminUrl('extending.php?panel=DBpretty/manage.php&operation=import'));
		} else {
			$this->widget('Widget_Notice')->set(_t('备份文件不存在！'), NULL, 'error');
			$this->response->goBack();
		}
	}

	public function downloadFile() {
		//已经省略
	}

	private function getDBInfo($dbHost, $dbUser, $dbPass, $dbCharset, $dbPort, $dbName) {
		$db = new Typecho_Db('Mysql'); 
		$db->addServer(array (
				'host'     => $dbHost,
				'user'     => $dbUser,
				'password' => $dbPass,
				'charset'  => $dbCharset,
				'port'     => $dbPort,
				'database' => $dbName,
		), Typecho_Db::READ | Typecho_Db::WRITE);
		
		try{
			$db->query('SELECT 1=1');
		}catch(Exception $e) {
			$this->response->throwJson(array('msg' => _t('数据库配置不正确'), 'status' => 'error'));
		}

		$result = $db->fetchRow($db->query('SELECT VERSION() as version'));
		$dbVersion = $result['version'];
		
		$result = $db->fetchRow($db->query("SHOW VARIABLES LIKE 'basedir'"));
		$mysql_base = $result['Value'];
		return array('dbObj' => $db, 'version' => $dbVersion, 'mysql_base' => $mysql_base);
	}

	private function keepLogin($db) {
		$user = $this->widget('Widget_User');
		$uid = $user->uid;
		if($uid > 0) {
			 $result = $db->fetchRow($db->select('authCode')->from('table.users')
                ->where('uid = ?', $uid));
			$authCode = $result['authCode'];
			$expire = $this->options->gmtTime + $this->options->timezone + 30*24*3600;
			Typecho_Cookie::set('__typecho_authCode', Typecho_Common::hash($authCode),
                $expire, $this->options->siteUrl);
		}
		
	}


}

?>